package com.yc.damai.web;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yc.damai.entity.Product;
import com.yc.damai.mapper.ProductMapper;
import com.yc.damai.vo.DacuOrder;
import com.yc.damai.vo.Result;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

@RestController
@RequestMapping("dacu")
public class DaCuDo {

    private long beginTime;
    private long length;
    private Timer timer;

    @Resource
    ProductMapper productMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    RabbitTemplate rabbitTemplate;

    @RequestMapping("begin")
    public synchronized String begin(
            @RequestParam(defaultValue = "60") int minutes
    ) {

        if (beginTime > 0) {
            return "活动已经开始";
        }

        // 清理前一次大促活动的数据
        clean();

        beginTime = System.currentTimeMillis();
        this.length = minutes * 60 * 1000;
        // 定时停止大促活动
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                DaCuDo.this.stop();
            }
        }, this.length);

        final Date date = new Date(beginTime + length);
        // 查询 pid <= 10 的商品作为 大促 商品
        LambdaQueryWrapper<Product> lqw = new LambdaQueryWrapper<>();
        lqw.lt(Product::getPid, 11);
        final List<Product> products = productMapper.selectList(lqw);
        // 商品价格 8折
        products.forEach(p -> p.setMarketPrice(p.getShopPrice() * 0.8));
        // 将商品数据保存到 redis 中
        final HashOperations opsForHash = redisTemplate.opsForHash();
        products.forEach(p -> {
            //opsForList.leftPush("dacuProducts", p);
            opsForHash.put("dacuProducts", p.getPid(), p);
        });
        return "大促活动开始! 截止时间: " + date;
    }

    @RequestMapping("stop")
    public synchronized String stop(){
        if (beginTime == 0) {
            return "活动已经停止";
        }
        // 取消定时自动听停止任务
        timer.cancel();
        timer = null;
        beginTime = 0;
        length = 0;
        clean();
        return "大促活动停止!";
    }

    @RequestMapping("getTime")
    public Map<String,Object> getTime(){
        Map<String,Object> map = new HashMap<>();
        map.put("beginTime", beginTime);
        map.put("length", length);
        return map;
    }

    private void clean(){
        // 清理大促商品数据
        redisTemplate.delete("dacuProducts");
        final Set<String> keys = redisTemplate.keys("dacu-*");
        keys.forEach(key -> redisTemplate.delete(key));
    }

    // 秒杀方法
    @RequestMapping("seckill")
    public Result seckill(int uid, int pid, int num) {
        // 判断是否处于大促活动期间
        if(beginTime == 0){
            return new Result(0, "大促活动未开始!", null);
        }
        final HashOperations opsForHash = redisTemplate.opsForHash();
        Product product = (Product) opsForHash.get("dacuProducts", pid);
        if (product == null) {
            return new Result(0, "该商品不是大促商品", null);
        }
        if (product.getCnt() < num) {
            return new Result(0, "该商品数量不足!", null);
        }
        SetOperations opsForSet = redisTemplate.opsForSet();
        // 检查 redis 该用户是否之前有秒杀过该商品
        final Boolean member = opsForSet.isMember("dacu-" + uid, pid);
        if (member) {
            return new Result(0, "该商品已经秒杀过!", null);
        }
        // 在 redis 中新增秒杀记录
        opsForSet.add("dacu-" + uid, pid);
        // 减商品数量
        product.setCnt(product.getCnt() - num);
        // 保存回 redis
        opsForHash.put("dacuProducts", pid, product);
        // 向消息队列发送订单消息
        DacuOrder order = new DacuOrder(uid, pid, num);
        rabbitTemplate.convertAndSend("damaiDacu", order);
        // 返回结果
        return new Result(1, "秒杀成功!", null);
    }

    @RequestMapping("getDacuProducts")
    public List<Product> getDacuProducts() {
        final HashOperations opsForHash = redisTemplate.opsForHash();
        final List<Product> products = opsForHash.values("dacuProducts");
        return products;
    }

}
